A computer system may include a virtual machine that allows execution of hardware independent programs. During program execution, objects may be created that use system memory. Typically, to avoid memory leaks in the computer system, the system memory used by an object is de-allocated after the object is no longer in use.
Conventionally, two methods are used to manage the memory used by objects created during program execution. The first method requires that the executing program monitors the usage of objects, and de-allocates the system memory used by each object when the object is no longer in use. This method requires an application programmer to carefully manage the memory used by each object created in the corresponding program. Further, this method places the responsibility of eliminating memory leaks on the application programmer.
The second method requires the use of an automatic memory management system, or garbage collector. A garbage collector may be a component located within a virtual machine, e.g., a garbage collector built into the Java™ Virtual Machine, or may be a separate entity interfaced with the virtual machine. A typical garbage collector monitors every object created for each task executing on the virtual machine. When the system needs to de-allocate the memory occupied by unused objects, the garbage collector performs garbage collection. Garbage collection is the process of de-allocating the memory of unused (e.g., dead, inactive, etc.) objects, where an unused object may have been created for a single task, or shared among multiple tasks.
A commonly-used garbage collector is a generational garbage collector. A generational garbage collector is based on the observation that most objects die at a young “age,” where the age of an object is measured as the time that the object has been alive, beginning with the creation of the object. Specifically, a generational garbage collector manages memory that is separated into two or more generations. Typically, a generational garbage collector manages a young generation and an old generation. During program execution, a newly created object is typically stored in the young generation. However, an object may be directly stored in the old generation for several reasons, including the object is too large for the young generation, the object is known to be long-lived, etc.
When memory is scarce, garbage collection is performed to de-allocate the memory of unused objects. Initially, young generation garbage collection is performed to de-allocate the memory of unused objects in the young generation. Objects that survive the young generation garbage collection (e.g., active objects) may be promoted to the old generation. During promotion of objects to the old generation, if enough memory is not available in the old generation for the objects to be promoted, then full garbage collection is performed. Full garbage collection is performed to de-allocate the memory of unused objects in both the old and young generations.
Further, garbage collection may be performed in a multi-tasking environment (e.g., on a multi-tasking virtual machine), where multiple programs (e.g., application domains, tasks, applications, etc.) execute concurrently and garbage collection is performed on one of the concurrently executing tasks. Further, tasks may be multi-threaded. In this case, an efficient strategy is to share the old generation amongst concurrently executing tasks and to assign to each task a private young generation. The strategy allows young generation garbage collection to be performed on the young objects allocated by one task only.
Garbage collection of the young generation of a task needs a consistent view of the old generation. However, in a multi-tasking environment, the old generation memory area may not remain consistent if concurrently executing tasks directly allocate objects into the old generation. A common solution is to suspend all tasks of the multi-tasking environment (i.e., to stop all threads of all the concurrently executing tasks). In some cases, this may affect the performance and scalability of a multi-tasking virtual machine.